package com.fmdrama.fetcher;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HeaderElement;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;

import com.fmdrama.Main;
import com.fmdrama.bean.Profile;
import com.fmdrama.bean.Video;
import com.fmdrama.db.VideoDao;
import com.fmdrama.util.Configuration;
import com.fmdrama.util.LOG;
import com.fmdrama.util.StringUtils;

/**
 * 播放页面抓取器
 */
public class PlayFetcher {
	private String cookie = "Hm_lt_640e8b7496ca5e87eb42eaddcd6e82ba=20140120104346; CNZZDATA770950=cnzz_eid%3D470312280-1390185653-%26ntime%3D1390202898%26cnzz_a%3D39%26ltime%3D1390185653660; CNZZDATA30052621=cnzz_eid%3D1286133588-1390185653-%26ntime%3D1390202898%26cnzz_a%3D19%26ltime%3D1390185658260; Hm_lvt_640e8b7496ca5e87eb42eaddcd6e82ba=1390185661; Hm_lpvt_640e8b7496ca5e87eb42eaddcd6e82ba=1390202899";
	private String code = null;
	private int reverseKey = 0;
	private HttpClient client = new HttpClient();
	private Profile profile;
	private VideoDao videoDao = new VideoDao();
	private List<Video> videos = null;
	private boolean started = false;
	
	/**
	 * 抓取
	 * @return
	 */
	public List<Video> fetch(Profile profile){
		started = true;
		this.profile = profile;
		PostMethod getMethod = null;
		try {
			long interval = Configuration.getLong("fetch.interval", 0);
			if(interval > 0){  //抓取间隔时间大于0，就暂停指定时间
				Thread.sleep(interval);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		try{
			videos = videoDao.queryByProfileId(profile.getId()); //根据profileId加载video到内存中，这样便于判断video是否已经抓取过了
			String url = "http://www.koreayh.com/play/" + profile.getId();
			getMethod = new PostMethod(url);
			client.executeMethod(getMethod);
			String result = getMethod.getResponseBodyAsString();
			Header[] headers = getMethod.getResponseHeaders("Set-Cookie");
			for(Header header : headers){
				HeaderElement[] eles = header.getElements();
				for(HeaderElement ele : eles){
					if("Hm_lpt_640e8b7496ca5e87eb42eaddcd6e82ba".equals(ele.getName())){
						code = ele.getValue(); //getPlayurl的时候需要
					}else if("Hm_lt_640e8b7496ca5e87eb42eaddcd6e82ba".equals(ele.getName())){
						reverseKey = Integer.parseInt(ele.getValue().charAt(ele.getValue().length()-1)+""); //从cookie中获得reverseKey，倒序视频播放id的时候，需要用到
					}
				}
				cookie = header.getValue() + "; " + cookie; //获得cookie信息，getPlayurl的时候需要
			}
			return parse(result);
		}catch (Exception e) {
			e.printStackTrace();
		}finally{
			getMethod.releaseConnection();
		}
		return null;
	}
	
	/**
	 * 解析，主要理由正则表达式，获取我们想要的数据
	 * @param source
	 * @return
	 */
	private List<Video> parse(String source){
		//解析视频标题
		Matcher filmNameMatcher = Pattern.compile("film_name = '(.*?)';").matcher(source);
		if(filmNameMatcher.find()){
			profile.setTitle(filmNameMatcher.group(1));
		}
		
		List<Video> list = new ArrayList<Video>();
		Pattern titlePattern = Pattern.compile("<span id=\"film_li_sort_(\\d+)\" title=\"(.*?)\">(.*?)</span>");
		Pattern pattern = Pattern.compile("<a class=\"(.*?)\" title=\"(.*?)\" href=\"javascript:;\" data-index=\"(.*?)\" data-count=\"(.*?)\" data-id=\"(.*?)\"></a>");
		Pattern p = Pattern.compile("<li><span id=\"film_li_sort([\\s\\S]*?)</li>");
		Matcher m = p.matcher(source);
		while(m.find()){
			String sub = m.group(0);
			Matcher matcher = pattern.matcher(sub);
			Video video = new Video();
			Matcher titleMatcher = titlePattern.matcher(sub);
			if(titleMatcher.find()){
				video.setTitle(titleMatcher.group(2));
			}
			while(matcher.find()){
				if(!started){
					return list;
				}
				String type = matcher.group(1);
				String dataIndex = matcher.group(3);
				if(!"tudou".equals(type) && !"youku".equals(type) && !"sohu".equals(type)){
					break;
				}
				
				video.setId(Long.parseLong(matcher.group(5))); //获得标签上的属性data-id的值作为id
				try{
					Video v = getVideo(video.getId());
					if(null != v){ //已经抓取过了，不在抓取
						video.setId(0);
						LOG.info("存在 -> " + v.toString());
						break;
					}
				}catch (Exception e) {
					e.printStackTrace();
				}
				
				String url = getPlayurl(dataIndex, type); //获取视频地址
					
				if(url.length() > 300){ //服务器出错，停顿一下
					try {
						long pause = Configuration.getLong("fetch.pause", 1000*10);
						LOG.warn("服务器出错，暂停" + pause + "(毫秒)");
						Thread.sleep(pause);
						video.setId(0);
						break;
					} catch (Exception e) {
						e.printStackTrace();
					}
				}

				if("youku".equals(type) && url.indexOf("/sid/")!=-1 && url.indexOf("/v.swf")!=-1){ //优酷的视频
					String	vid = url.substring(url.indexOf("/sid/")+5, url.indexOf("/v.swf"));
					vid = reverseId(vid);
					video.setYouku(vid);
				}else if("tudou".equals(type)){  //土豆的视频
					if(!url.startsWith("http://")){
						url = reverseId(url);
					}
					video.setTudou(url);
				}else if("sohu".equals(type)){  //搜狐的视频
					video.setSohu(url.replace("autoplay=false", "autoplay=true"));
				}
				try {
					long interval = Configuration.getLong("fetch.interval", 0);
					if(interval > 0){  //抓取间隔时间大于0，就暂停指定时间
						Thread.sleep(interval);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
			if(video.getId()>0 && (StringUtils.isNotEmpty(video.getYouku()) || StringUtils.isNotEmpty(video.getTudou()) || StringUtils.isNotEmpty(video.getSohu()) )){
				video.setProfileId(profile.getId());
				video.setFtime(new Date());
				list.add(video);
				LOG.info("抓取 -> " + video.toString());
			}
		}
		return list;
	}
	
	/**
	 * 获取视频播放id或者地址
	 * @param dataIndex
	 * @param type
	 * @return
	 */
	private String getPlayurl(String dataIndex, String type){
		PostMethod postMethod = null;
		try{
			postMethod = new PostMethod("http://www.koreayh.com/player/playurl");
			postMethod.addParameter("film", profile.getId()+"");
			postMethod.addParameter("film_", (Long.parseLong(dataIndex)-1)+"");
			postMethod.addParameter("type", type);
			postMethod.addParameter("film_code", code);
			postMethod.addRequestHeader("Cookie", cookie);
			client.executeMethod(postMethod);
			String result = postMethod.getResponseBodyAsString();
			return result;
		}catch (Exception e) {
			e.printStackTrace();
		}finally{
			postMethod.releaseConnection();
		}
		return null;
	}
	
	/**
	 * 对获取到的视频id倒序
	 * @param id
	 * @return
	 */
	private String reverseId(String id) {
		String c = "";
		String a = "";
		if (reverseKey > 1 && id.length() >= reverseKey) {
			a = id.substring(reverseKey);
			for (int reverseKey = a.length() - 1; reverseKey >= 0; reverseKey--) {
				c += a.substring(reverseKey, reverseKey + 1);
			}
			id = id.substring(0, reverseKey) + c;
		}
		return id;
	}
	
	
	private Video getVideo(long id){
		for(Video video : videos){
			if(video.getId() == id){
				return video;
			}
		}
		return null;
	}
	
	
	public void close(){
		started = false;
		client.getHttpConnectionManager().closeIdleConnections(0);
	}
}
